#include "StdAfx.h"
#include "NilKey.h"

bool operator == (const CNilKey  &cLeft,const CNilKey  & cRight)
{
	return CNilKey::Compare(cLeft,cRight)==0;
};
CNilKey::CNilKey(void)
{
}

CNilKey::~CNilKey(void)
{
}
CNilKey::CNilKey(const CNilKey & tmp)
{
	for(int i=SIZE-1;i>=0;i--)
	{
		this->m_rgId[i]=tmp.m_rgId[i];
	}
}
CNilKey::CNilKey(const string & tmp)
{
	this->FromString(tmp);
}
string CNilKey::ToString()
{
	string strValue="";
	for(int i=0;i<SIZE;i++)
	{
		char tmp[128];
		sprintf_s<128>(tmp,"%u ",this->m_rgId[SIZE-i-1]);
		strValue.append(tmp);
	}
	strValue.append(";");
	return strValue;
};
CNilKey& CNilKey::operator = (const CNilKey & tmp)
{
	for(int i=SIZE-1;i>=0;i--)
	{
		this->m_rgId[i]=tmp.m_rgId[i];
	}
	return *this;
};
bool CNilKey::FromString(const string & strValue)
{
	ZeroMemory(this->m_rgId,sizeof(unsigned long)*SIZE);
	string strId(strValue);
	int nPos=(int)strId.find_last_of(';');
	if(string::npos==nPos)
	{
		return false;
	}
	else
	{
		strId.erase(nPos);
	}
	while((nPos = (int)strId.find_last_of(' ')) == strId.length()-1)
	{
		strId.erase(nPos);
	}
	while(strId.c_str()[0]==' ')
	{
		strId.erase(0,1);
	}
	for(int i=0;i<SIZE-1;i++)
	{
		nPos = (int)strId.find_last_of(' ');
		if(nPos==string::npos)
		{
			return false;
		}
		this->m_rgId[i]=(unsigned long)_atoi64(strId.substr(nPos).c_str());
		strId.erase(nPos);
	}
	this->m_rgId[SIZE-1]=(unsigned long)_atoi64(strId.c_str());
	return true;
};

int CNilKey::GetDistance(const CNilKey& cLeft,const CNilKey& cRight)
{
	const static unsigned long Hex[256]={
			0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,
			1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
			1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
			2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
			1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
			2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
			2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
			3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
			1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
			2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
			2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
			3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
			2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
			3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
			3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
			4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};

	unsigned long nRes;
	nRes = 0;
	for(int i=0;i<SIZE;i++)
	{
		unsigned long nDiff =cLeft.m_rgId[i]^cRight.m_rgId[i];
		int nTime = sizeof(unsigned long)  ;
		__asm
		{
 				mov eax, dword ptr [nDiff]
				mov ebx, 0
				mov   ESI, dword ptr [nTime] 
	  loop1:   
				mov edx,eax
				and edx, 0xff
				shl edx,2
				add ebx,dword ptr [Hex+edx] 
				
				shr eax,8
				
				dec   ESI   
				cmp   ESI,0   
				jnz   loop1 
				add dword ptr [nRes],ebx
		}
			
	}
	return nRes;
};
int CNilKey::Compare(const CNilKey& cLeft,const CNilKey& cRight)
{
	for(int i=SIZE-1;i>=0;i--)
	{
		if(cLeft.m_rgId[i]==cRight.m_rgId[i])
		{
			continue;
		}
		else
		{
			if(cLeft.m_rgId[i]>cRight.m_rgId[i])
			{
				return i+1;
			}
			else
			{
				return -1-i;
			}
		}
	}
	return 0;
};